from django.core.mail import send_mail
from django.conf import settings
from django.contrib.auth.models import User
from django.utils import timezone
from django.db import transaction
from .models import LeaveApplication, ApprovalRecord, UserProfile
import logging

logger = logging.getLogger(__name__)


class LeaveApprovalService:
    """请假审批服务"""
    
    @staticmethod
    def submit_application(leave_application, user):
        """提交请假申请"""
        with transaction.atomic():
            leave_application.status = 'submitted'
            leave_application.submitted_at = timezone.now()
            leave_application.save()
            
            # 创建提交记录
            ApprovalRecord.objects.create(
                leave_application=leave_application,
                approver=user,
                action='submit',
                comments='提交请假申请'
            )
            
            # 发送通知给下一个审批人
            next_approver = leave_application.get_next_approver()
            if next_approver:
                LeaveApprovalService._send_approval_notification(
                    leave_application, next_approver, 'pending'
                )
            
            return True
    
    @staticmethod
    def approve_application(leave_application, approver, comments=''):
        """批准请假申请"""
        with transaction.atomic():
            current_status = leave_application.status
            
            if current_status == 'submitted':
                # 主管审批
                leave_application.status = 'supervisor_approved'
                leave_application.supervisor_approver = approver
                action_type = 'approve'
                
                # 检查是否需要人事审批
                if leave_application.days_requested > 3:
                    # 需要人事审批
                    next_approver = leave_application.get_next_approver()
                    if next_approver:
                        LeaveApprovalService._send_approval_notification(
                            leave_application, next_approver, 'pending'
                        )
                else:
                    # 直接批准
                    leave_application.status = 'approved'
                    leave_application.approved_at = timezone.now()
                    
            elif current_status == 'supervisor_approved':
                # 人事审批
                leave_application.status = 'approved'
                leave_application.hr_approver = approver
                leave_application.approved_at = timezone.now()
                action_type = 'approve'
            else:
                raise ValueError(f'无法从状态 {current_status} 进行审批')
            
            leave_application.save()
            
            # 创建审批记录
            ApprovalRecord.objects.create(
                leave_application=leave_application,
                approver=approver,
                action=action_type,
                comments=comments or '批准申请'
            )
            
            # 发送通知给申请人
            LeaveApprovalService._send_approval_notification(
                leave_application, leave_application.applicant, 
                'approved' if leave_application.status == 'approved' else 'intermediate_approved'
            )
            
            return True
    
    @staticmethod
    def reject_application(leave_application, approver, comments=''):
        """拒绝请假申请"""
        with transaction.atomic():
            leave_application.status = 'rejected'
            leave_application.save()
            
            # 创建拒绝记录
            ApprovalRecord.objects.create(
                leave_application=leave_application,
                approver=approver,
                action='reject',
                comments=comments or '拒绝申请'
            )
            
            # 发送通知给申请人
            LeaveApprovalService._send_approval_notification(
                leave_application, leave_application.applicant, 'rejected'
            )
            
            return True
    
    @staticmethod
    def cancel_application(leave_application, user, comments=''):
        """取消请假申请"""
        if not leave_application.can_be_cancelled():
            raise ValueError('该申请无法取消')
        
        with transaction.atomic():
            leave_application.status = 'cancelled'
            leave_application.save()
            
            # 创建取消记录
            ApprovalRecord.objects.create(
                leave_application=leave_application,
                approver=user,
                action='cancel',
                comments=comments or '取消申请'
            )
            
            return True
    
    @staticmethod
    def return_application(leave_application, approver, comments=''):
        """退回请假申请"""
        with transaction.atomic():
            leave_application.status = 'draft'
            leave_application.save()
            
            # 创建退回记录
            ApprovalRecord.objects.create(
                leave_application=leave_application,
                approver=approver,
                action='return',
                comments=comments or '退回申请'
            )
            
            # 发送通知给申请人
            LeaveApprovalService._send_approval_notification(
                leave_application, leave_application.applicant, 'returned'
            )
            
            return True
    
    @staticmethod
    def _send_approval_notification(leave_application, recipient, notification_type):
        """发送审批通知邮件"""
        try:
            subject_map = {
                'pending': f'待审批：{leave_application.applicant.get_full_name()}的请假申请',
                'approved': '请假申请已批准',
                'intermediate_approved': '请假申请已通过主管审批',
                'rejected': '请假申请已拒绝',
                'returned': '请假申请已退回',
            }
            
            message_map = {
                'pending': f'''
您好，{recipient.get_full_name()}！

您有一个待审批的请假申请：

申请人：{leave_application.applicant.get_full_name()}
请假类型：{leave_application.leave_type.name}
请假时间：{leave_application.start_date} 至 {leave_application.end_date}
请假天数：{leave_application.days_requested}天
请假原因：{leave_application.reason}

请登录系统进行审批。
                ''',
                'approved': f'''
您好，{recipient.get_full_name()}！

您的请假申请已被批准：

请假类型：{leave_application.leave_type.name}
请假时间：{leave_application.start_date} 至 {leave_application.end_date}
请假天数：{leave_application.days_requested}天

请合理安排工作交接。
                ''',
                'intermediate_approved': f'''
您好，{recipient.get_full_name()}！

您的请假申请已通过主管审批，正在等待人事部门审批：

请假类型：{leave_application.leave_type.name}
请假时间：{leave_application.start_date} 至 {leave_application.end_date}
请假天数：{leave_application.days_requested}天
                ''',
                'rejected': f'''
您好，{recipient.get_full_name()}！

很抱歉，您的请假申请已被拒绝：

请假类型：{leave_application.leave_type.name}
请假时间：{leave_application.start_date} 至 {leave_application.end_date}
请假天数：{leave_application.days_requested}天

如有疑问，请联系相关审批人。
                ''',
                'returned': f'''
您好，{recipient.get_full_name()}！

您的请假申请已被退回，请修改后重新提交：

请假类型：{leave_application.leave_type.name}
请假时间：{leave_application.start_date} 至 {leave_application.end_date}
请假天数：{leave_application.days_requested}天

请登录系统查看详细信息并重新提交。
                '''
            }
            
            subject = subject_map.get(notification_type, '请假申请通知')
            message = message_map.get(notification_type, '请假申请状态已更新')
            
            if recipient.email:
                send_mail(
                    subject=subject,
                    message=message,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[recipient.email],
                    fail_silently=True
                )
                logger.info(f'邮件通知已发送给 {recipient.username}: {subject}')
            else:
                logger.warning(f'用户 {recipient.username} 没有邮箱地址，无法发送通知')
                
        except Exception as e:
            logger.error(f'发送邮件通知失败: {str(e)}')
    
    @staticmethod
    def get_pending_approvals(user):
        """获取待审批的申请"""
        user_profile = user.userprofile
        pending_applications = []
        
        if user_profile.role in ['supervisor', 'admin']:
            # 主管可以审批下属的申请
            subordinates = UserProfile.objects.filter(supervisor=user_profile)
            subordinate_users = [sub.user for sub in subordinates]
            
            pending_applications.extend(
                LeaveApplication.objects.filter(
                    applicant__in=subordinate_users,
                    status='submitted'
                )
            )
        
        if user_profile.role in ['hr', 'admin']:
            # 人事可以审批需要人事审批的申请
            pending_applications.extend(
                LeaveApplication.objects.filter(
                    status='supervisor_approved',
                    days_requested__gt=3
                )
            )
        
        return list(set(pending_applications))  # 去重
    
    @staticmethod
    def can_user_approve(user, leave_application):
        """检查用户是否可以审批指定申请"""
        user_profile = user.userprofile
        
        # 不能审批自己的申请
        if leave_application.applicant == user:
            return False
        
        if leave_application.status == 'submitted':
            # 主管审批阶段
            if user_profile.role in ['supervisor', 'admin']:
                # 检查是否是申请人的直属上级
                applicant_profile = leave_application.applicant.userprofile
                return applicant_profile.supervisor == user_profile
        
        elif leave_application.status == 'supervisor_approved':
            # 人事审批阶段
            if user_profile.role in ['hr', 'admin']:
                return leave_application.days_requested > 3
        
        return False


class LeaveBalanceService:
    """请假余额服务"""
    
    @staticmethod
    def get_user_balance(user, leave_type, year=None):
        """获取用户指定类型的请假余额"""
        from .models import LeaveBalance
        
        if year is None:
            year = timezone.now().year
        
        balance, created = LeaveBalance.objects.get_or_create(
            user=user,
            leave_type=leave_type,
            year=year,
            defaults={
                'total_days': LeaveBalanceService._get_default_balance(user, leave_type),
                'used_days': 0
            }
        )
        
        return balance
    
    @staticmethod
    def _get_default_balance(user, leave_type):
        """获取默认余额"""
        if leave_type.name == '年假':
            return user.userprofile.annual_leave_days
        elif leave_type.name == '病假':
            return 30  # 病假一般每年30天
        elif leave_type.name == '事假':
            return 10  # 事假一般每年10天
        else:
            return 5   # 其他类型默认5天
    
    @staticmethod
    def update_balance_on_approval(leave_application):
        """审批通过时更新余额"""
        if leave_application.status == 'approved':
            balance = LeaveBalanceService.get_user_balance(
                leave_application.applicant,
                leave_application.leave_type,
                leave_application.start_date.year
            )
            balance.used_days += leave_application.days_requested
            balance.save()
    
    @staticmethod
    def check_balance_sufficient(user, leave_type, days_requested, year=None):
        """检查余额是否充足"""
        balance = LeaveBalanceService.get_user_balance(user, leave_type, year)
        return balance.remaining_days >= days_requested
